﻿#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
#include <vector>
#include <deque>
#include <cstdlib>
#include <ctime>
#include <string>
#include <cmath>

const int GRID_SIZE = 40;
const int GRID_WIDTH = 20;
const int GRID_HEIGHT = 15;
const int WINDOW_WIDTH = GRID_SIZE * GRID_WIDTH;
const int WINDOW_HEIGHT = GRID_SIZE * GRID_HEIGHT;

enum Direction { UP, DOWN, LEFT, RIGHT };

struct Position {
    int x, y;
    bool operator==(const Position& other) const {
        return x == other.x && y == other.y;
    }
};

// 残影结构
struct AfterImage {
    std::deque<Position> positions;
    std::deque<std::wstring> chars;
    float lifetime;

    AfterImage(const std::deque<Position>& pos, const std::deque<std::wstring>& ch)
        : positions(pos), chars(ch), lifetime(0.3f) {
    }
};

class Snake {
public:
    std::deque<Position> body;
    std::deque<std::wstring> characters;
    Direction direction;
    bool hasHalfPhrase;  // 是否吃完前半句
    bool hasFullPhrase;  // 是否吃完完整句子
    float glowTimer;     // 光效计时器
    float rainbowTimer;  // 跑马灯计时器
    bool isDashing;      // 是否在冲刺中
    float dashTimer;     // 冲刺计时器
    float dashCooldown;  // 冲刺冷却时间

    Snake() {
        body.push_back({ GRID_WIDTH / 2, GRID_HEIGHT / 2 });
        characters.push_back(L"头");
        direction = RIGHT;
        hasHalfPhrase = false;
        hasFullPhrase = false;
        glowTimer = 0.0f;
        rainbowTimer = 0.0f;
        isDashing = false;
        dashTimer = 0.0f;
        dashCooldown = 0.0f;
    }

    void updateEffects(float deltaTime) {
        glowTimer += deltaTime;
        rainbowTimer += deltaTime;

        // 更新冲刺状态
        if (isDashing) {
            dashTimer -= deltaTime;
            if (dashTimer <= 0.0f) {
                isDashing = false;
            }
        }

        // 更新冷却时间
        if (dashCooldown > 0.0f) {
            dashCooldown -= deltaTime;
        }
    }

    void startDash() {
        if (dashCooldown <= 0.0f && !isDashing) {
            isDashing = true;
            dashTimer = 0.5f; // 冲刺持续0.5秒
            dashCooldown = 2.0f; // 冷却2秒
        }
    }

    bool canDash() const {
        return dashCooldown <= 0.0f && !isDashing;
    }

    void checkPhraseCompletion() {
        // 检查是否吃完前半句（7个字：卡耐基的反复手）
        if (characters.size() >= 8 && !hasHalfPhrase) {  // 8 = 头 + 7个字
            hasHalfPhrase = true;
        }

        // 检查是否吃完完整句子（14个字）
        if (characters.size() >= 15 && !hasFullPhrase) {  // 15 = 头 + 14个字
            hasFullPhrase = true;
        }
    }

    void move() {
        Position newHead = body.front();

        switch (direction) {
        case UP: newHead.y--; break;
        case DOWN: newHead.y++; break;
        case LEFT: newHead.x--; break;
        case RIGHT: newHead.x++; break;
        }

        body.push_front(newHead);
        body.pop_back();
        // 移除最后一个字符（尾巴）
        if (characters.size() > body.size()) {
            characters.pop_back();
        }
    }

    void grow(const std::wstring& character) {
        Position newHead = body.front();

        switch (direction) {
        case UP: newHead.y--; break;
        case DOWN: newHead.y++; break;
        case LEFT: newHead.x--; break;
        case RIGHT: newHead.x++; break;
        }

        body.push_front(newHead);
        // 把吃到的字符加到尾部
        characters.push_back(character);

        // 检查是否完成短语
        checkPhraseCompletion();
    }

    bool checkCollision() {
        const Position& head = body.front();

        if (head.x < 0 || head.x >= GRID_WIDTH ||
            head.y < 0 || head.y >= GRID_HEIGHT) {
            return true;
        }

        for (size_t i = 1; i < body.size(); i++) {
            if (body[i] == head) {
                return true;
            }
        }

        return false;
    }
};

class Food {
public:
    Position pos;
    std::wstring character;
    std::vector<std::wstring> foodChars;
    int currentIndex;

    Food() {
        foodChars.push_back(L"卡");
        foodChars.push_back(L"耐");
        foodChars.push_back(L"基");
        foodChars.push_back(L"的");
        foodChars.push_back(L"反");
        foodChars.push_back(L"复");
        foodChars.push_back(L"手");
        foodChars.push_back(L"的");
        foodChars.push_back(L"西");
        foodChars.push_back(L"游");
        foodChars.push_back(L"逆");
        foodChars.push_back(L"向");
        foodChars.push_back(L"之");
        foodChars.push_back(L"旅");
        currentIndex = 0;
        spawn();
    }

    void spawn() {
        pos.x = rand() % GRID_WIDTH;
        pos.y = rand() % GRID_HEIGHT;
        // 按顺序生成字符
        character = foodChars[currentIndex];
        currentIndex = (currentIndex + 1) % foodChars.size(); // 循环
    }

    bool checkCollision(const Position& snakeHead) {
        return pos == snakeHead;
    }
};

int main() {
    srand(static_cast<unsigned>(time(nullptr)));

    sf::RenderWindow window(sf::VideoMode({ WINDOW_WIDTH, WINDOW_HEIGHT }),
        L"逆向西游");
    window.setFramerateLimit(10);

    // 加载中文字体
    sf::Font font;
    if (!font.openFromFile("C:/Windows/Fonts/msyh.ttc")) {
        if (!font.openFromFile("C:/Windows/Fonts/simhei.ttf")) {
            if (!font.openFromFile("C:/Windows/Fonts/simsun.ttc")) {
                return -1;
            }
        }
    }

    Snake snake;
    Food food;
    int score = 0;
    bool gameOver = false;
    std::vector<AfterImage> afterImages; // 残影列表
    float afterImageSpawnTimer = 0.0f;

    sf::Clock clock;
    float moveTimer = 0.0f;
    const float moveInterval = 0.15f;

    while (window.isOpen()) {
        while (const auto event = window.pollEvent()) {
            if (event->is<sf::Event::Closed>()) {
                window.close();
            }

            if (const auto* keyPressed = event->getIf<sf::Event::KeyPressed>()) {
                if (!gameOver) {
                    if (keyPressed->code == sf::Keyboard::Key::Up && snake.direction != DOWN) {
                        snake.direction = UP;
                    }
                    else if (keyPressed->code == sf::Keyboard::Key::Down && snake.direction != UP) {
                        snake.direction = DOWN;
                    }
                    else if (keyPressed->code == sf::Keyboard::Key::Left && snake.direction != RIGHT) {
                        snake.direction = LEFT;
                    }
                    else if (keyPressed->code == sf::Keyboard::Key::Right && snake.direction != LEFT) {
                        snake.direction = RIGHT;
                    }
                    else if (keyPressed->code == sf::Keyboard::Key::Space) {
                        snake.startDash();
                    }
                }

                // 游戏结束时用 Enter 键重新开始
                if (gameOver && keyPressed->code == sf::Keyboard::Key::Enter) {
                    snake = Snake();
                    food = Food();
                    score = 0;
                    gameOver = false;
                    afterImages.clear();
                }
            }
        }

        if (!gameOver) {
            float deltaTime = clock.restart().asSeconds();
            moveTimer += deltaTime;
            snake.updateEffects(deltaTime);

            // 更新残影
            afterImageSpawnTimer += deltaTime;
            for (auto it = afterImages.begin(); it != afterImages.end();) {
                it->lifetime -= deltaTime;
                if (it->lifetime <= 0.0f) {
                    it = afterImages.erase(it);
                }
                else {
                    ++it;
                }
            }

            // 冲刺时移动速度加快
            float currentMoveInterval = snake.isDashing ? moveInterval * 0.3f : moveInterval;

            if (moveTimer >= currentMoveInterval) {
                moveTimer = 0.0f;

                // 冲刺时生成残影
                if (snake.isDashing && afterImageSpawnTimer >= 0.05f) {
                    afterImages.push_back(AfterImage(snake.body, snake.characters));
                    afterImageSpawnTimer = 0.0f;
                }

                if (food.checkCollision(snake.body.front())) {
                    snake.grow(food.character);
                    score++;
                    food.spawn();

                    bool onSnake = true;
                    while (onSnake) {
                        onSnake = false;
                        for (const auto& segment : snake.body) {
                            if (food.pos == segment) {
                                food.spawn();
                                onSnake = true;
                                break;
                            }
                        }
                    }
                }
                else {
                    snake.move();
                }

                if (snake.checkCollision()) {
                    gameOver = true;
                }
            }
        }
        else {
            clock.restart(); // 暂停时钟
        }

        // 渲染
        window.clear(sf::Color(20, 20, 40));

        // 绘制网格线
        for (int i = 0; i <= GRID_WIDTH; i++) {
            sf::RectangleShape line(sf::Vector2f(1, static_cast<float>(WINDOW_HEIGHT)));
            line.setPosition(sf::Vector2f(static_cast<float>(i * GRID_SIZE), 0));
            line.setFillColor(sf::Color(40, 40, 60));
            window.draw(line);
        }
        for (int i = 0; i <= GRID_HEIGHT; i++) {
            sf::RectangleShape line(sf::Vector2f(static_cast<float>(WINDOW_WIDTH), 1));
            line.setPosition(sf::Vector2f(0, static_cast<float>(i * GRID_SIZE)));
            line.setFillColor(sf::Color(40, 40, 60));
            window.draw(line);
        }

        // 绘制残影
        for (const auto& afterImage : afterImages) {
            float alpha = (afterImage.lifetime / 0.3f) * 150.0f;
            for (size_t i = 0; i < afterImage.positions.size(); i++) {
                float segmentSize = (i == 0) ? GRID_SIZE : GRID_SIZE - 2.0f;
                float offset = (i == 0) ? 0.0f : 1.0f;

                sf::RectangleShape segment(sf::Vector2f(segmentSize, segmentSize));
                segment.setPosition(sf::Vector2f(
                    static_cast<float>(afterImage.positions[i].x * GRID_SIZE + offset),
                    static_cast<float>(afterImage.positions[i].y * GRID_SIZE + offset)
                ));

                // 残影颜色根据蛇的状态
                if (i == 0) {
                    segment.setFillColor(sf::Color(100, 200, 100, static_cast<unsigned char>(alpha)));
                }
                else if (snake.hasFullPhrase) {
                    segment.setFillColor(sf::Color(150, 150, 255, static_cast<unsigned char>(alpha)));
                }
                else if (snake.hasHalfPhrase) {
                    segment.setFillColor(sf::Color(200, 200, 100, static_cast<unsigned char>(alpha)));
                }
                else {
                    segment.setFillColor(sf::Color(100, 200, 100, static_cast<unsigned char>(alpha)));
                }
                window.draw(segment);

                // 残影文字
                sf::Text text(font, afterImage.chars[i], 24);
                text.setFillColor(sf::Color(0, 0, 0, static_cast<unsigned char>(alpha)));

                sf::FloatRect textBounds = text.getLocalBounds();
                text.setPosition(sf::Vector2f(
                    afterImage.positions[i].x * GRID_SIZE + (GRID_SIZE - textBounds.size.x) / 2.0f,
                    afterImage.positions[i].y * GRID_SIZE + (GRID_SIZE - textBounds.size.y) / 2.0f - 5
                ));
                window.draw(text);
            }
        }

        // 绘制蛇
        for (size_t i = 0; i < snake.body.size(); i++) {
            // 蛇头稍微大一点
            float segmentSize = (i == 0) ? GRID_SIZE : GRID_SIZE - 2.0f;
            float offset = (i == 0) ? 0.0f : 1.0f;

            sf::RectangleShape segment(sf::Vector2f(segmentSize, segmentSize));
            segment.setPosition(sf::Vector2f(
                static_cast<float>(snake.body[i].x * GRID_SIZE + offset),
                static_cast<float>(snake.body[i].y * GRID_SIZE + offset)
            ));

            // 根据完成状态设置颜色
            if (i == 0) {
                // 蛇头
                segment.setFillColor(sf::Color(100, 200, 100));
            }
            else if (snake.hasFullPhrase) {
                // 完成整句：跑马灯效果
                float hue = fmod((snake.rainbowTimer * 200.0f + i * 25.0f), 360.0f);
                int h = static_cast<int>(hue / 60.0f);
                float f = hue / 60.0f - h;
                float q = 1.0f - f;

                sf::Color rainbowColor;
                switch (h % 6) {
                case 0: rainbowColor = sf::Color(255, static_cast<unsigned char>(f * 255), 0); break;
                case 1: rainbowColor = sf::Color(static_cast<unsigned char>(q * 255), 255, 0); break;
                case 2: rainbowColor = sf::Color(0, 255, static_cast<unsigned char>(f * 255)); break;
                case 3: rainbowColor = sf::Color(0, static_cast<unsigned char>(q * 255), 255); break;
                case 4: rainbowColor = sf::Color(static_cast<unsigned char>(f * 255), 0, 255); break;
                case 5: rainbowColor = sf::Color(255, 0, static_cast<unsigned char>(q * 255)); break;
                }
                segment.setFillColor(rainbowColor);
            }
            else if (snake.hasHalfPhrase) {
                // 完成前半句：发光效果
                float glow = 0.5f + 0.5f * sin(snake.glowTimer * 5.0f);
                unsigned char brightness = static_cast<unsigned char>(150 + glow * 105);
                segment.setFillColor(sf::Color(brightness, brightness, 50));
            }
            else {
                // 普通蛇身
                segment.setFillColor(sf::Color(50, 150, 50));
            }
            window.draw(segment);

            // 绘制汉字
            sf::Text text(font, snake.characters[i], 24);
            text.setFillColor(sf::Color::Black);

            sf::FloatRect textBounds = text.getLocalBounds();
            text.setPosition(sf::Vector2f(
                snake.body[i].x * GRID_SIZE + (GRID_SIZE - textBounds.size.x) / 2.0f,
                snake.body[i].y * GRID_SIZE + (GRID_SIZE - textBounds.size.y) / 2.0f - 5
            ));
            window.draw(text);
        }

        // 绘制食物（发光效果，类似前半句）
        float foodGlow = 0.5f + 0.5f * sin(clock.getElapsedTime().asSeconds() * 5.0f);
        unsigned char foodBrightness = static_cast<unsigned char>(180 + foodGlow * 75);

        sf::RectangleShape foodRect(sf::Vector2f(GRID_SIZE - 2.0f, GRID_SIZE - 2.0f));
        foodRect.setPosition(sf::Vector2f(
            static_cast<float>(food.pos.x * GRID_SIZE + 1),
            static_cast<float>(food.pos.y * GRID_SIZE + 1)
        ));
        foodRect.setFillColor(sf::Color(foodBrightness, foodBrightness / 3, foodBrightness / 3));
        window.draw(foodRect);

        sf::Text foodText(font, food.character, 24);
        foodText.setFillColor(sf::Color::Black);

        sf::FloatRect foodTextBounds = foodText.getLocalBounds();
        foodText.setPosition(sf::Vector2f(
            food.pos.x * GRID_SIZE + (GRID_SIZE - foodTextBounds.size.x) / 2.0f,
            food.pos.y * GRID_SIZE + (GRID_SIZE - foodTextBounds.size.y) / 2.0f - 5
        ));
        window.draw(foodText);

        // 绘制分数和冲刺状态
        sf::Text scoreText(font, L"得分: " + std::to_wstring(score), 20);
        scoreText.setFillColor(sf::Color::White);
        scoreText.setPosition(sf::Vector2f(10, 10));

        // 添加半透明黑色背景让分数更清晰
        sf::FloatRect scoreBounds = scoreText.getLocalBounds();
        sf::RectangleShape scoreBg(sf::Vector2f(scoreBounds.size.x + 20, scoreBounds.size.y + 15));
        scoreBg.setPosition(sf::Vector2f(5, 5));
        scoreBg.setFillColor(sf::Color(0, 0, 0, 150));
        window.draw(scoreBg);
        window.draw(scoreText);

        // 显示冲刺状态
        std::wstring dashStatus;
        sf::Color dashColor;
        if (snake.isDashing) {
            dashStatus = L"冲刺中! ⚡";
            dashColor = sf::Color::Yellow;
        }
        else if (snake.dashCooldown > 0.0f) {
            int cooldownSec = static_cast<int>(snake.dashCooldown) + 1;
            dashStatus = L"冷却: " + std::to_wstring(cooldownSec) + L"s";
            dashColor = sf::Color(150, 150, 150);
        }
        else {
            dashStatus = L"按空格冲刺!";
            dashColor = sf::Color::Green;
        }

        sf::Text dashText(font, dashStatus, 18);
        dashText.setFillColor(dashColor);
        dashText.setPosition(sf::Vector2f(10, 40));

        sf::FloatRect dashBounds = dashText.getLocalBounds();
        sf::RectangleShape dashBg(sf::Vector2f(dashBounds.size.x + 20, dashBounds.size.y + 15));
        dashBg.setPosition(sf::Vector2f(5, 35));
        dashBg.setFillColor(sf::Color(0, 0, 0, 150));
        window.draw(dashBg);
        window.draw(dashText);

        // 游戏结束提示
        if (gameOver) {
            sf::Text gameOverText(font, L"游戏结束！按空格键重新开始", 30);
            gameOverText.setFillColor(sf::Color::Red);

            sf::FloatRect bounds = gameOverText.getLocalBounds();
            gameOverText.setPosition(sf::Vector2f(
                (WINDOW_WIDTH - bounds.size.x) / 2.0f,
                (WINDOW_HEIGHT - bounds.size.y) / 2.0f
            ));
            window.draw(gameOverText);
        }

        window.display();
    }

    return 0;
}